/*
创 建 人：王曙光
创建时间：2011-10-13
功能描述：MD5,SHA1,SHA1256
*/
package com.jinher.lib.encrypt
{
	import com.jinher.lib.encrypt.MD5;
	import com.jinher.lib.encrypt.SHA1;
	import flash.utils.ByteArray;
	import mx.utils.SHA256;

	/**
	 * Provides an all static API which wraps the SHA1, SHA-256 and
	 * MD5 encryption algorithms, respectively, in order to allow a
	 * supported encryption algorithm to be applied to a String with or without salt
	 */
	public final class Encryption
	{
		/**
		 * Defines the constant which represents an SHA-256 hash
		 * algorithm
		 */
		private static const CRYPTIT_SHA256:String="SHA-256";

		/**
		 * Defines the constant which represents a US Secure
		 * Hash Algorithm 1 (SHA1)
		 */
		private static const CRYPTIT_SHA1:String="SHA1";

		/**
		 * Defines the constant which represents an MD5 Message
		 * Digest Algorithm
		 */
		private static const CRYPTIT_MD5:String="MD5";

		private static function GenerateSalt(maxchars:Number=15):String
		{
			var randomChar:Array=['number', 'letter'];

			var pass:String="";

			var i:int=0;
			for (i; i < maxchars; i++)
			{
				//Runs a loop according to the maximum amount of chars
				var num:Number=Math.floor(Math.random() * (3 - 1));
				//Random number between 3 and 0
				if (randomChar[num] == 'number')
				{
					//if the char will be a number
					pass+='' + Math.floor(Math.random() * (10 - 1)) + '';
						//add a number to finalString between 0 and 10
				}
				else
				{
					//If letter
					pass+=String.fromCharCode(Math.floor(Math.random() * (90 - 65)) + 65);
						//add a letter from A-Z
				}
			}
			return pass;
		}
		/****************************************************************
		 * 对外公开
		 ***************************************************************/

		/**
		 * Provides a utility operation from which a String is encrypted
		 * to the specified encryption with or without salt
		 *
		 * @example the following example demonstrates each Encryption
		 * type being performed on the same String
		 *
		 * <listing version="3.5">
		 *
		 * var password:String = "iamboredsoiblog";
		 *
		 * without SALT
		 * trace( Encryption.encrypt( password, Encryption.CRYPTIT_MD5 ) );
		 * //
		 *
		 * trace( Encryption.encrypt( password, Encryption.CRYPTO_SHA1 ) );
		 * //
		 *
		 * trace( Encryption.encrypt( password, Encryption.CRYPTO_SHA256) );
		 * //
		 * </listing>
		 *
		 * @param  the String which is to be encrypted
		 * @param  a constant representing the required encryption
		 * @param use salt or not on the encryption
		 * @param lenght of the salt
		 * @return an encrypted version of the source parameter
		 */
		public static function encrypt(source:String, type:String, UseSalt:Boolean=false, SaltLenght:Number=10):String
		{
			var encryption:String;

			var strSalt:String=GenerateSalt(SaltLenght);

			if (UseSalt == true)
			{
				source=strSalt + "" + source + "" + strSalt;
			}

			switch (type)
			{
				case CRYPTIT_MD5:
					encryption=MD5.hash(source);
					break;
				case CRYPTIT_SHA1:
					encryption=SHA1.hash(source);
					break;
				case CRYPTIT_SHA256:
					var ba:ByteArray=new ByteArray();
					ba.writeUTFBytes(source)
					encryption=SHA256.computeDigest(ba);
					break;
			}

			if (UseSalt == true)
			{
				encryption=encryption + ":" + strSalt;
			}

			return encryption;
		}

		/**
		 * @param the String which is to be checked on encrypted password
		 * @param the encrypted password
		 * @param used or no used salt
		 * @return true or false
		 */
		public static function CheckCrypt(pw:String, encrpw:String, type:String, UseSalt:Boolean=false):Boolean
		{
			var decryption:String;

			if (UseSalt == true)
			{
				var parts:Array=encrpw.split(':');
				var strSalt:String=parts[1];
				pw=strSalt + "" + pw + "" + strSalt;
			}

			switch (type)
			{
				case CRYPTIT_MD5:
					decryption=MD5.hash(pw);
					break;
				case CRYPTIT_SHA1:
					decryption=SHA1.hash(pw);
					break;
				case CRYPTIT_SHA256:
					var ba:ByteArray=new ByteArray();
					ba.writeUTFBytes(pw)
					decryption=SHA256.computeDigest(ba);
					break;
			}

			if (UseSalt == true)
			{
				decryption=decryption + ":" + strSalt;
			}

			if (decryption == encrpw)
			{
				return true;
			}
			else
			{
				return false;
			}
			//return decryption;
		}
	}
}
